<?php

require_once('krn_tab.php');
require_once('commons_rules.php');
require_once('commons_mail.php');
require_once('commons_log.php');
require_once('fct_date.php');
require_once('fct_dao_compte.php');
require_once('fct_dao_mariage.php');
require_once('fct_dao_marie.php');
require_once('fct_dao_ceremonie.php');
require_once('fct_dao_type_ceremonie.php');
require_once('fct_dao_statut.php');

/**
 * Retourne les informations relatives au mariage : noms et prénoms des mariés; jour, mois et année du mariage
 * @param $idMariage Identifiant du mariage pour lequel on veut créer le cookie
 * @return array : tableau associatif
 */
function getInfosMariage($idMariage) {
	static $infosMariage = null;
	
	if (is_null($idMariage)) {
		// throw new Exception('Aucun identifiant de mariage n\'a été fourni', ERR_BAD_REQUEST);
		return null;
	}
	
	if (is_null($infosMariage) || (!isset($infosMariage[$idMariage]))) {
		$aryDataApp = getDataApp($idMariage);
		
		//Informations sur la date du mariage
		$time = strtotime($aryDataApp[KEY_DATE_MARIAGE]);
		$jour = date('d', $time);
		$mois = date('m', $time);
		$annee = date('Y', $time);
		
		$infosMariage[$idMariage] = array
									(NOM_CONJOINT1			=> getFirstWord($aryDataApp[KEY_MARIE1][KEY_NOM_MARIE])
									,PRENOM_CONJOINT1		=> getFirstWord($aryDataApp[KEY_MARIE1][KEY_PRENOM_MARIE])
									,NOM_CONJOINT2			=> getFirstWord($aryDataApp[KEY_MARIE2][KEY_NOM_MARIE])
									,PRENOM_CONJOINT2		=> getFirstWord($aryDataApp[KEY_MARIE2][KEY_PRENOM_MARIE])
									,JOUR_MARIAGE			=> intval($jour)
									,MOIS_MARIAGE			=> intval($mois)
									,ANNEE_MARIAGE			=> intval($annee)
									,KEY_ID_MARIAGE			=> $aryDataApp[KEY_ID_MARIAGE]
									,KEY_ID_COMPTE			=> $aryDataApp[KEY_ID_COMPTE]
									,KEY_URI_ALIAS			=> getNomSiteUrlFromCompte($aryDataApp[KEY_ID_COMPTE])
									);
	}
	
	return $infosMariage[$idMariage];
}

/**
 * Retourne l'identifiant du mariage courant soit depuis le paramètre de l'URL ou alors dans le cookie
 * s'il existe.<br />
 * Null est retournée si l'identifiant ne peut pas être calculé
 * @return int
 */
function getIdMariage() {
	$idMariage = null;
	if (isset($_REQUEST['idMariage'])) {
		$idMariage = intval($_REQUEST['idMariage']);
	} else {
		$aryDataApp = getCookieAppValue(COOKIE_APP_NAME, COOKIE_APP_LIFE_TIME_MINUTE, null);
		if (!is_null($aryDataApp) && isset($aryDataApp[KEY_ID_MARIAGE])) {
			$idMariage = intval($aryDataApp[KEY_ID_MARIAGE]);
		}
	}
	return $idMariage;
}

/**
 * Get and return all information related to the wedding with identifier $idMariage<br />
 * Throw an exception with code ERR_BAD_REQUEST in case some information related to the wedding
 * could not be retrieved from the database.<br />
 * Some other exceptions might be thrown from the database. Normally with error code ERR_NOT_ACCEPTABLE
 * @param $idMariage
 * @return array
			(KEY_MARIAGE	=> $mariage
			,KEY_COMPTE		=> $compte
			,KEY_STATUT		=> $statut
			,KEY_MARIE1		=> $marie1
			,KEY_MARIE2		=> $marie2
			);
 */
function getAllInfosByIdMariage($idMariage) {
	//Initialize the variable only for the first time this function is called in a transaction
	static $allInfos = null;
	
	if ($allInfos == null) {
		// Get the wedding
		$mariage = getMariage($idMariage);
		if (($mariage == null) && (count($mariage) == 0)) {
			throw new Exception("Le mariage d'identifiant $idMariage n'existe pas", ERR_BAD_REQUEST);
		}
		
		// Get the account using the wedding account id
		$compte = getCompte($mariage['ID_COMPTE']);
		if (($compte == null) && (count($compte) == 0)) {
			throw new Exception('Le compte d\'identifiant '.$mariage['ID_COMPTE'].' n\'existe pas pour le mariage d\'identifiant '.$idMariage, ERR_BAD_REQUEST);
		}
		
		// Get the account status
		$statut = getStatutById($compte['ID_STATUT']);
		if (($statut == null) && (count($statut) == 0)) {
			throw new Exception('Le statut d\'identifiant '.$compte['ID_STATUT'].' n\'existe pas. Identifiant du compte : '.$mariage['ID_COMPTE'], ERR_BAD_REQUEST);
		}
		
		// Get the future married information
		$marie1 = getMarie($mariage['ID_MARIE1']);
		$marie2 = getMarie($mariage['ID_MARIE2']);
		if (($marie1 == null) && (count($marie1) == 0)) {
			throw new Exception('Le conjoint n°1 d\'identifiant '.$mariage['ID_MARIE1'].' n\'existe pas. Identifiant du mariage : '.$idMariage, ERR_BAD_REQUEST);
		}
		if (($marie2 == null) && (count($marie2) == 0)) {
			throw new Exception('Le conjoint n°2 d\'identifiant '.$mariage['ID_MARIE2'].' n\'existe pas. Identifiant du mariage : '.$idMariage, ERR_BAD_REQUEST);
		}
		
		$allInfos = array
					(KEY_MARIAGE	=> $mariage
					,KEY_COMPTE		=> $compte
					,KEY_STATUT		=> $statut
					,KEY_MARIE1		=> $marie1
					,KEY_MARIE2		=> $marie2
					);
	}
	
	return $allInfos;
}

/**
 * Retourne le header commun de la page HTML à  afficher
 * @param isAdmin : true si l'on charge la page d'admin et false si l'on charge la page du site
 * @return string
 */
function getHeaderPage($isAdmin) {
	//Récupération de l'identifiant du mariage à charger dans le cookie
	try {
		$idMariage = getIdMariage();
		$infosMariage = getInfosMariage($idMariage);
	} catch (Exception $e) {
		logError('Impossible de récupérer des informations de mariage pour l\'uri ' . getCurrentBaseUrl());
		logError($e -> getTraceAsString());
	}
	
	$cssFile = 'main.css';
	if (!is_null($infosMariage)) {
		$title = 'du mariage de '.$infosMariage[PRENOM_CONJOINT1].' et '.$infosMariage[PRENOM_CONJOINT2];
		$content = $infosMariage[PRENOM_CONJOINT1].', '.$infosMariage[PRENOM_CONJOINT2].', mariage, '.
					strtolower($infosMariage[MOIS_MARIAGE]).', '. $infosMariage[ANNEE_MARIAGE];
	} else {
		$title = 'des mariages';
		$content = '';
	}
	
	if ($isAdmin) {
		$title = 'Page d\'administration '.$title;
	} else {
		//On met la première lettre en majuscule
		$title = ucfirst($title);
	}
	
	
	return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xml:lang="fr" xmlns="http://www.w3.org/1999/xhtml" lang="fr">
<head>
	<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
	<meta name="KEYWORDS" content="'.$content.'"/>
	<link rel="stylesheet" type="text/css" href="/wedding/styles/'.$cssFile.'" media="screen"/>
	<!--[if IE]>
    <link rel="stylesheet" type="text/css" href="/wedding/styles/main_ie.css" />
    <![endif]-->
    <script type="text/javascript"
      src="https://maps.googleapis.com/maps/api/js?key='.GOOGLE_API_KEY.'&sensor=true">
    </script>
	<script src="/wedding/ihm/js/main.js" type="text/javascript"></script>
    <script src="/wedding/js/jquery-1.10.2.min.js" type="text/javascript"></script>
    <script src="/wedding/js/jquery-ui-1.10.3.min.js" type="text/javascript"></script>
	<title>'.$title.'</title>
</head>
<body onload="initialize(\'map\')">
	<div id="content">';
}

/**
 * Retourne le footer commun de la page HTML
 * @return string
 */
function getFooterPage() {
	return '</div><p><br/></p><p><br/></p></body></html>';
}

/**
 * Convertit en HTML la chaîne de caractères en paramètre
 * @param $string chaîne de caractères dont les caractères spéciaux seront transformés en entité HTML
 */
function htmlEncode($string) {
	return htmlentities($string, ENT_NOQUOTES, 'UTF-8',false);
}

/**
 * Transforme la chaîne de caractères en paramètre en caractères normaux. Toutes les entités HTML sont converties en caractères normaux
 * @param $string chaîne de caractères à convertir en caractères normaux
 */
function htmlDecode($string) {
	return html_entity_decode($string, ENT_NOQUOTES, 'UTF-8');
}

/**
 * Retourne l'url permettant d'atteindre le fichier courant.
 * @return string : l'url menant au fichier courant
 */
function getCurrentBaseUrl() {
	//URL de la forme /xxxx/yyy/.../fff.php
	$uriComplete = $_SERVER['REQUEST_URI'];
	$urlSplit = explode('/', $uriComplete);
	
	$urlComplete = 'http://'.$_SERVER['HTTP_HOST'];
	for ($i=0; $i<count($urlSplit); $i++) {
		if ($urlSplit[$i] === '') {
			continue;
		}
		$urlComplete .= '/'.$urlSplit[$i];
	}
	return $urlComplete;
}

/**
 * Construis et retourne l'url de base $baseUri en la complétant avec les paramètres fournis dans $params si tableau
 * non vide
 * @param $baseUri base de l'URI
 * @param $params paramètres éventuels de l'URL
 */
function buildUrl($baseUri, $params=array()) {
	if (!is_array($params) || count($params) == 0) {
		return $baseUri;
	} else {
		$query = '';
		foreach ($params as $param => $value) {
			if ($query !== '') {
				$query .= '&';
			}
			$query .= $param.'='.urlencode($value);
		}
		return ($query !== '') ? $baseUri.'?'.$query : $baseUri;
	}
}

/**
 * Parse l'url en paramètre et retourne la valeur du paramètre "onglet" de la requête<br />
 * Retourne null si le paramètre "onglet" n'existe pas
 * @param $url url à parser
 * @return string : valeur du paramètre "onglet" de l'url ou null
 */
function getIdOngletFromUrl($url) {
	if (trim($url) !== '') {
		$query = parse_url($url, PHP_URL_QUERY);
		$queryArray = explode('&', $query);
		foreach ($queryArray as $queryVal) {
			$queryValArray = explode('=', $queryVal);
			if ($queryValArray[0] === 'onglet') {
				return intval($queryValArray[1]);
			}
		}
	}
	return null;
}

/**
 * Parse le numéro de téléphone en paramètre et le retourne sur 10 chiffres en supprimant tous les espaces.<br />
 * Lève des exceptions dans le cas où le numéro n'est pas un numéro standard français
 * @param string $telephone
 * @return string
 */
function parserTelephoneFr($telephone) {
	if ($telephone == null) {
		return null;
	}
	$newTel = str_replace(' ', '', trim($telephone));
	if (strstr($newTel, '+') !== false) {
		if ((strlen($newTel) !== 12) || (substr($newTel, 0, 3) !== '+33')) {
			//Numéro de téléphone différent de +33xxxxxxxx
			throw new Exception('Le numéro de téléphone fourni n\'est pas français. Numéro téléphone : '.$newTel, ERR_TECHNICAL);
		} else {
			return '0'.substr($newTel,3);
		}
	} else if ((strlen($newTel) !== 10) || (substr($newTel, 0, 1) !== '0') || (preg_match('/^0[1-9]{9}$/', $newTel) !== 1)) {
		//Numéro de téléphone différent de +33xxxxxxxx
		throw new Exception('Le numéro de téléphone fourni n\'est pas français. Numéro téléphone : '.$newTel, ERR_TECHNICAL);
	} else {
		// A ce stade, le numéro de téléphone est à 10 chiffres et commence par 0, on le retourne tel quel
		return $newTel;
	}
}

/**
 * Retourne le premier mot contenu dans $names. La première chaîne est celle située avant le premier espace<br />
 * Un mot est une suite de chaînes de caractères alphabétiques non séparés par un espace, pouvant contenir (mais ne
 * commençant pas par) un apostrophe ou un tiret.<br />
 * La première lettre du premier mot retourné est mise en majuscule<br />
 *
 * @param String $names noms séparés par des espaces
 * @return String premier mot contenu dans la chaîne $names. Chaîne vide si $names nul ou vide
 */
function getFirstWord($names) {
	if (is_null($names) || (trim($names) === '')) {
		return '';
	}
	$words = str_word_count(trim($names), 1);
	return ucfirst($words[0]);
}

/**
 * Retourne le tableau associatif des données applicatives de l'application<br />
 * Lève une exception si elle survient
 * @param $idMariage Identifiant du mariage pour lequel on veut créer le cookie
 * @return array
 */
function getDataApp($idMariage) {
	try {
		return getCookieAppValue(COOKIE_APP_NAME, COOKIE_APP_LIFE_TIME_MINUTE, $idMariage);
	} catch (Exception $e) {
		if ($e -> getCode() === ERR_UNAUTHORIZED) {
			logError('Exception survenue lors de la lecture du cookie. Message : '.$e->getMessage());
			//On retourne la valeur de la base
			return getValueFromDBForCookie($idMariage);
		} else {
			logFatal($e->getCode().' - '.$e->getMessage() . ' - ' . $e->getTraceAsString());
			throw $e;
		}
	}
}

/**
 * Crée le cookie de nom $cookieName pour une durée de vie de $cookieLifeTime minutes
 * @param $cookieName nom du cookie
 * @param $cookieLifeTime durée de vie en minutes du cookie
 * @param $idMariage Identifiant du mariage pour lequel on veut créer le cookie
 * @return bool : true si le cookie a été envoyé au navigateur sans garantie de création côté client / false autrement
 */
function createCookieApp($cookieName, $cookieLifeTime, $idMariage) {
	$computedVal = computeCookieValueApp($cookieName, $idMariage);
	logInfo("Creation du cookie $cookieName reussie");
	return setcookie($cookieName.'_'.$_SERVER['SERVER_NAME'], $computedVal, time() + $cookieLifeTime*60);
}

/**
 * Retourne la valeur du cookie applicatif $cookieName. Le crée s'il n'existe pas
 * @param string $cookieName nom du cookie sans le suffixe
 * @param int $cookieLifeTime temps de vie du cookie en minutes
 * @param $idMariage Identifiant du mariage pour lequel on veut créer le cookie
 * @return array
 * @throws Exception Exception levée en cas de non authentification de cookie
 */
function getCookieAppValue($cookieName, $cookieLifeTime, $idMariage) {
	static $aryValCookie = null;
	$finalName = $cookieName.'_'.$_SERVER['SERVER_NAME'];
	if ($aryValCookie === null) {
		if (!isset($_COOKIE[$finalName]) && !is_null($idMariage)) {
			//Le cookie n'existe pas ou plus, l'identifiant du mariage est connu, on crée le cookie
			createCookieApp($cookieName, $cookieLifeTime, $idMariage);
		}
		
		if (!isset($_COOKIE[$finalName])) {
			//Le cookie n'a pas pu être créé ou n'existe pas, on logue et on retourne les valeurs de la base
			logWarn("Le cookie $finalName n'a pas été créé a priori.");
			if (!is_null($idMariage)) {
				$aryValCookie = getValueFromDBForCookie($idMariage);
			}
		} else {
			//Récupération de la valeur du cookie
			$serializedCookieVal = $_COOKIE[$finalName];
			
			$aryCookieVal = unserialize($serializedCookieVal);
			$valueOfCookie = $aryCookieVal[COOKIE_KEY_VAL];
			$hashedExpected = $aryCookieVal[COOKIE_KEY_HASHED];
			
			//Vérification de l'authenticité du cookie
			$separator = '::';
			$hashedVal = $finalName . $separator . serialize($valueOfCookie) . $separator . 'notre mariage sera enorme';
			$hashedValue = hash_hmac('sha256', $hashedVal, COOKIE_ENCRYPT_KEY);
			
			if ($hashedExpected !== $hashedValue) {
				//Les valeurs hashées sont différentes
				logFatal('Exception levee car le cookie n\'est pas authentique.');
				throw new Exception('Le cookie n\'est pas authentique', ERR_UNAUTHORIZED);
			}
			
			//Affectation de la valeur du cookie
			logDebug('Lecture dans le cookie');
			$aryValCookie = $valueOfCookie;
		}
	} else {
		logDebug('Lecture dans le tableau statique contenant les valeurs du cookie');
	}
	return $aryValCookie;
}

/**
 * Retourne la valeur du cookie $cookieName
 * @param string $cookieName nom du cookie
 * @param $idMariage Identifiant du mariage pour lequel on veut créer le cookie
 * @return string : valeur du cookie
 */
function computeCookieValueApp($cookieName, $idMariage) {
	$finalName = $cookieName.'_'.$_SERVER['SERVER_NAME'];
	$separator = '::';
	
	//Valeur du cookie
	$cookieVal = getValueFromDBForCookie($idMariage);
		
	//Sérialisation de la table des valeurs
	$serialCookieVal = serialize($cookieVal);
	
	//Calcul de la valeur hashée
	$hashedVal = $finalName . $separator . $serialCookieVal . $separator . 'notre mariage sera enorme';
	$hashedValue = hash_hmac('sha256', $hashedVal, COOKIE_ENCRYPT_KEY);
		
	//Tableau final à mettre dans le cookie
	$finalValCookie = array
						(COOKIE_KEY_VAL		=> $cookieVal
						,COOKIE_KEY_HASHED	=> $hashedValue
						);
	
	return serialize($finalValCookie);
}

/**
 * Retourne la valeur du cookie
 * @param $idMariage Identifiant du mariage pour lequel on veut créer le cookie
 * @return tableau associatif de la date du mariage et des informations des deux mariés
 */
function getValueFromDBForCookie($idMariage) {
	logInfo('Recuperation des donnees applicatives dans la base pour la mariage d\'identifiant '.$idMariage);
	
	// Get all information rdelated to the wedding with identifier $idMariage
	$allInfos = getAllInfosByIdMariage($idMariage);
	
	$aryMarie1 = array
		(KEY_CIVILITE		=> $allInfos[KEY_MARIE1]['CIVILITE']
		,KEY_NOM_MARIE		=> $allInfos[KEY_MARIE1]['NOM']
		,KEY_PRENOM_MARIE	=> $allInfos[KEY_MARIE1]['PRENOM']
		);
	$aryMarie2 = array
		(KEY_CIVILITE		=> $allInfos[KEY_MARIE2]['CIVILITE']
		,KEY_NOM_MARIE		=> $allInfos[KEY_MARIE2]['NOM']
		,KEY_PRENOM_MARIE	=> $allInfos[KEY_MARIE2]['PRENOM']
		);
		
	//Valeurs des cookies
	return array
		(KEY_ID_MARIAGE		=> $allInfos[KEY_MARIAGE]['ID']
		,KEY_ID_COMPTE		=> $allInfos[KEY_COMPTE]['ID']
		,KEY_DATE_MARIAGE	=> $allInfos[KEY_MARIAGE]['DATE_MARIAGE']
		,KEY_MARIE1			=> $aryMarie1
		,KEY_MARIE2			=> $aryMarie2
		);
}

/**
 * Retourne le html de l'onglet de sélection des menus
 * @param int $idMariage : identifiant du mariage
 * @param int $currentIdTab le code de l'onglet choisi
 * @param string $type : type de menu à charger
 * @return string : block div contenant le menu des onglets de navigation
 */
function getOngletMenu($idMariage, $currentIdTab=null, $type='USER') {
	$menu = '<div id="menu" class="bold">';
	if ($type === 'USER') {
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_ACCUEIL'), $currentIdTab, $type);
		$menu .= '<p class="menuItem menuItemTitle alignCenter">Informations utiles</p>';
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_ORGA_JOUR_J'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_BRUNCH'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_DIRECTIONS'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_HEBERGEMENT'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_LISTE_MARIAGE'), $currentIdTab, $type);
		$menu .= '<p class="menuItem menuItemTitle alignCenter">Informations diverses</p>';
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_RENCONTRE'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_INFO_PRATIQUE'), $currentIdTab, $type);
		$menu .= '<p class="menuItem menuItemTitle alignCenter">Photos</p>';
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_PHOTO_CONSULTATION'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_PHOTO_UPLOAD'), $currentIdTab, $type);
		//$menu .= '<p class="menuItem"><span class="menuItemIddle" style="color:#000">Consulter les photos du mariage</span></p>';
		//$menu .= '<p class="menuItem"><span class="menuItemIddle" style="color:#000">Envoyer vos photos du mariage</span></p>';
		$menu .= '<p class="menuItem menuItemTitle alignCenter">Contacts</p>';
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_CONTACT'), $currentIdTab, $type);
		//$menu .= getOngletMenuItem(tabGetIdByCode('TAB_PRESENCE'), $currentIdTab);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_LIVRE_OR'), $currentIdTab, $type);
	} else if ($type === 'ADMIN') {
		$menu .= '<p class="menuItem menuItemTitle alignCenter">Administration</p>';
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_ADMIN_MARIAGE'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_ADMIN_INVITE'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_ADMIN_LIVRE_OR'), $currentIdTab, $type);
		$menu .= getOngletMenuItem($idMariage, tabGetIdByCode('TAB_ADMIN_ADRESSE'), $currentIdTab, $type);
	}
	$menu .= '</div>';
	return $menu;
}

/**
 * Retourne le html de l'onglet correspondant à afficher
 * @param int $idMariage : identifiant du mariage
 * @param int $idTab identifiant de l'onglet
 * @param int $currentIdTab id de l'onglet courant
 * @param string $type : type de menu à charger
 * @return string : html de l'onglet à afficher
 */
function getOngletMenuItem($idMariage, $idTab, $currentIdTab=null, $type='USER') {
	//Tableau de tous les onglets fils par id
	static $aryIdTabChildren = null;
	if ($aryIdTabChildren === null) {
		$aryIdTabChildren = tabGetAllTabChildrenById();
	}
	
	//Tableau des id d'onglet déjà traités
	static $listIdTabChildrenDone = null;
	if ($listIdTabChildrenDone === null) {
		$listIdTabChildrenDone = array();
	}
	
	//On vérifie si l'id d'onglet courant a déjà été traité comme onglet fils ou s'il est défini comme onglet fils
	if (isset($aryIdTabChildren[$idTab]) || in_array($idTab, $listIdTabChildrenDone)) {
		//On ne fait rien
		return '';
	}
	
	if (is_null($currentIdTab) || !is_numeric($currentIdTab) || ($currentIdTab < 0) || ($currentIdTab > tabGetMax())) {
		//Par défaut valué à ACCUEIL
		$currentIdTab = tabGetDefault();
	}
	
	$appliWeddingPath = '';
	if ($type === 'ADMIN') {
		$appliWeddingPath = 'admin/';
	}
	
	// Récupération de l'alias de l'uri pour le compte correspondant au mariage dont on construit la page
	$infosMariage = getInfosMariage($idMariage);
	$uriAlias = $infosMariage[KEY_URI_ALIAS];
	
	$aryCssClasses = getCssClassesMenuItem($idTab, $currentIdTab);
	$menuItem = '<p class="menuItem"><a href="/wedding/'.$appliWeddingPath.$uriAlias.'/'.$idTab.'"><span'.$aryCssClasses['color'].'>'.tabGetName($idTab).'</span></a></p>';
	
	//Tableau des onglets fils pour l'id d'onglet courant
	$listChildrenOfIdTab = tabGetCodeTabChildren($idTab);
	if (!is_null($listChildrenOfIdTab)) {
		//Il existe des onglets fils, on les rajoute au menu et à la liste des id de menus fils traités
		foreach ($listChildrenOfIdTab as $codeTabChild) {
			$idTabChild = tabGetIdByCode($codeTabChild);
			if (tabGetToDisplay($idTabChild)) {
				//On affiche l'onglet que s'il est tagué comme onglet à afficher
				$aryCssClasses = getCssClassesMenuItem($idTabChild, $currentIdTab);
				//$menuItem .= '<p class="menuItem"><span'.$aryCssClasses['class'].'><a href="index.php?onglet='.$idTabChild.'"><span'.$aryCssClasses['color'].'>'.tabGetName($idTabChild).'</span></a></span></p>';
				$menuItem .= '<p class="sousMenuItem"><a href="/wedding/'.$appliWeddingPath.$uriAlias.'/'.$idTabChild.'"><span'.$aryCssClasses['color'].'>'.tabGetName($idTabChild).'</span></a></p>';
				$listIdTabChildrenDone[] = $idTabChild;
			}
		}
	}
	
	return $menuItem;
}

/**
 * Retourne un tableau des classes pour l'affichage des items de menu d'ongle
 * @param $idTab identifiant de l'onglet à afficher
 * @param $currentIdTab identifier de l'onglet à mettre en surbrillance
 * @return array : tableau associatif des css de classe et couleur. Les clés sont 'class' et 'color'
 */
function getCssClassesMenuItem($idTab, $currentIdTab) {
	$class = '';
	$classColor = '';
	if ($idTab == $currentIdTab) {
		//L'onglet courant à afficher est l'onglet choisi, on définit la classe css correspondante pour affichage en surbrillance
		$classColor = ' class="menuItemSelectedColor"';
	} else {
		$class .= ' class="menuItemIddle"';
	}
	return array
			('class'	=> $class
			,'color'	=> $classColor
			);
}

/**
 * Return the value of the field to print. Return an empty String if field is null
 * @param $fldValue field value
 * @return String
 */
function printField($fldValue) {
	if (is_null($fldValue)) {
		return '';
	} else {
		return trim($fldValue);
	}
}

/**
 * Print the array given in input
 * @param $array
 * @return String
 */
function printArray($array) {
	if (!is_array($array)) {
		return 'Not an array';
	} else {
		strval($array);
	}
}

/**
 * Return the value of the index $idx of the array $array if it is set. Return an empty value if not set
 * @param $idx index to print
 * @param $array array
 * @return string
 */
function printFieldArray($idx, $array) {
	if (!isset($array[$idx]) || is_null($array[$idx])) {
		return '';
	}
	return trim($array[$idx]);
}

/**
 * Supprime les accents des lettres qui en portent.
 * @param string $string
 * @return La chaîne de caractères $string sans accent
 */
function accentCleaner($string) {
	$string = utf8_decode($string);
	$cleaned = strtr
		($string
		,utf8_decode('ÁÂÀÅÃÄÇÉÊÈËÍÎÌÏÑÓÔÒØÕÖŠÚÛÙÜÝŸáâàåãäçéêèëíîìïñóôòøõöšúûùüýÿ')
		,'AAAAAACEEEEIIIINOOOOOOSUUUUYYaaaaaaceeeeiiiinoooooosuuuuyy'
		);
	return utf8_encode($cleaned);
}

/**
 * Retourne l'alphabet français
 * @return array : alphabet français
 */
function getAlphabet() {
	static $alphabet = null;
	if ($alphabet === null) {
		$alphabet = array
						('A','B','C','D','E','F','G','H','I','J','K','L','M'
						,'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
						);
	}
	return $alphabet;
}

/**
 * Substring the text provided in input to $maxLimit minus 3 and adds 3 points; in case length of $text is
 * strictly greater than $maxLimit. Otherwise $text is returned
 * @param $text
 * @param $maxLimit
 * @return string
 */
function substring($text, $maxLimit) {
	if (is_null($text)) {
		return null;
	} elseif (!is_string($text)) {
		return false;
	}
	$lenText = strlen(trim($text));
	if ($lenText <= $maxLimit) {
		//Size of original text is smaller than the maximum, the whole text can be displayed
		return trim($text);
	} else {
		//Size of original text is greater than the maximum, the whole text will be cut to the maximum limit minus 3
		return substr(trim($text), 0, $maxLimit - 3) . '...';
	}
}

/**
 * Sérialise le tableau en entrée en une chaîne de caractères.
 * Si le tableau en entrée n'en est pas un, false est retourné.
 * Si les deux séparateurs de clé et de valeur sont nuls, le tableau est sérialisé par valeur
 * en appliquant comme séparateur le séparateur par défaut défini dans les constantes.
 * Si l'un des séparateurs est nuls, la sérialisation ne se fait que pour les clés ou les valeurs
 * selon que c'est le séparateur de clé qui est non nul ou non.
 * Si les deux séparateurs sont non nuls, la sérialisation se fait sur les clés et les valeurs avec la
 * règle clé puis séparateur de clé puis valeur correspondante puis séparateur de valeur et ainsi de suite.
 * @param array $array
 * @param string $separatorValue
 * @param string $separatorKey
 * @return string ou false
 */
function serializeArray($array, $separatorValue, $separatorKey=null) {
	if (is_null($array) || !is_array($array)) {
		return false;
	}
	
	if (is_null($separatorKey) && is_null($separatorValue)) {
		$separatorVal = SEPARATOR_VALEUR_DEFAUT;
	}
	
	$serialized = '';
	foreach ($array as $key => $value) {
		if (!is_null($separatorKey)) {
			$serialized .= $key . $separatorKey;
		}
		
		if (!is_null($separatorValue)) {
			$serialized .= $value . $separatorValue;
		}
		
		if (is_null($separatorKey) && is_null($separatorValue)) {
			$serialized .= $value . $separatorVal;
		}
	}
	
	if ($serialized !== '') {
		$serialized = substr($string, 0, str_len($serialized) - 2);
	}
	
	return $serialized;
}

/**
 * Sérialise les clés du tableau en paramètre avec le séparateur de clé donné en deuxième paramètre.
 * Si le séparateur fourni est nul, false est retourné.
 * @param array $array
 * @param string $separatorKey
 * @return string ou false
 */
function serializeArrayByKey($array, $separatorKey) {
	if (is_null($separatorKey)) {
		return false;
	}
	return serializeArray($array, null, $separatorKey);
}

/**
 * Sérialise les valeurs du tableau en paramètre avec le séparateur de valeur donné en deuxième paramètre.
 * Si le séparateur fourni est nul, le séparateur par défaut défini en constantes est utilisé
 * @param array $array
 * @param string $separatorKey
 * @return string ou false
 */
function serializeArrayByValue($array, $separatorValue) {
	return serializeArray($array, $separatorValue, null);
}

/**
 * Gère un cas d'exception et redirige vers la page d'erreur depuis l'onglet de code $currCodeTab
 * @param $exception
 * @param $currCodeTab
 * @param $uriErrorPage
 */
function redirectErrorPage($exception, $currCodeTab, $uriErrorPage) {
	$excMsg = $exception -> getCode() . ' : ' . $exception -> getMessage();
	logFatal('L\'erreur suivante est survenue et a empêché le chargement de l\'onglet '.tabGetIdByCode($currCodeTab).'. Erreur : '.$excMsg);

	// Redirection vers la page d'erreur
	$uriError = $uriErrorPage . '&errorMsg=' . rawurlencode($excMsg);
	header('Location: '.$uriError);
}

